import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:kq_flutter_core_widget/utils/kq_screen_util.dart';
import 'package:kq_flutter_core_widget/utils/text_filed_utils.dart';
import 'package:kq_flutter_core_widget/widgets/textField/kq_text_selection.dart';

import '../../config/kq_pad_global.dart';
import '../../resources/images.dart';
import '../../resources/kq_pad_theme_colors.dart';
import '../../resources/l10n/kq_pad_intl.dart';
import '../../theme/kq_theme_manager.dart';

/// 通用输入框
///
/// @author 周卓
///
/// 无边框
class KqPadTextFiled extends StatefulWidget {
  /// 是否多行
  final bool multiline;

  /// 键盘类型
  final TextInputType? inputType;

  /// 是否可编辑
  final bool editable;

  /// 是否自动聚焦
  final bool autofocus;

  /// 是否使用外部容器高度，比如用户意见反馈那种大输入框，默认false
  final bool useParentHeight;

  /// 非编辑模式是否强制显示hint
  final bool forceShowPlaceHolder;

  /// 隐藏输入内容
  final bool password;

  /// 光标颜色
  final Color? cursorColor;

  /// 文字选中背景颜色
  final Color? selectionColor;

  /// 字体大小
  final double? fontSize;

  /// 文字颜色
  final Color? textColor;

  /// 提示文字颜色
  final Color? placeHolderTextColor;

  /// 默认值
  final String? defValue;

  /// 默认光标位置，不传则在最后面
  final int? defOffset;

  /// 最大行数
  final int? maxLines;

  /// 最大字符数，默认不限制
  final int? maxCharCount;

  /// 对其方式
  final TextAlign? textAlign;

  /// 垂直对齐方式
  final TextAlignVertical? textAlignVertical;

  /// 键盘提交按钮样式
  final TextInputAction? textInputAction;

  /// 提示文字
  final String? placeHolder;

  /// TextEditingController
  final TextEditingController? controller;

  /// 输入内容限制，建议使用[TextInputFormatUtils]
  final List<TextInputFormatter>? inputFormatters;

  /// 数值变化监听
  final ValueChanged<String>? onChanged;

  /// 键盘提交监听
  final ValueChanged<String>? onSubmitted;

  /// 数值变化监听，带EditController对象
  final Function(String value, TextEditingController controller)?
      onChangedWithEditController;

  /// 清空按钮点击监听
  final VoidCallback? onCleared;

  /// 焦点变化
  final Function(bool hasFocus)? onFocusChanged;

  /// 点击清空按钮是否自动移除焦点和收起键盘
  final bool unFocusWhenCleared;

  /// 是否显示清空按钮
  final bool enableClearButton;

  /// 用于监听停顿回调，基于onTextChange，500ms没有输入则回调，避免频繁调用接口。
  final Function(String str)? onMonitor;

  /// 输入框文字颜色，设置这个之后，[fontSize]、[textColor]将失效
  final TextStyle? textStyle;

  /// 提示文字样式，设置这个之后，[placeHolderTextColor]将失效
  final TextStyle? hintStyle;

  /// 光标高度
  final double? cursorHeight;

  /// 光标圆角
  final Radius? cursorRadius;

  /// 自定义统计字数的文本
  final String? counterText;

  /// 统计字数的文本样式
  final TextStyle? counterStyle;

  /// 自定义统计字数的控件
  final Widget? counter;

  /// 同TextFiled的isCollapsed
  final bool isCollapsed;

  /// StrutStyle
  final StrutStyle? strutStyle;

  /// 自定义输入框左边的控件
  final Widget? customLeftWidget;

  /// 自定义输入框右边的控件
  final Widget? customRightWidget;

  /// 固定高度
  final double? fixedHeight;

  /// 外部边框
  final Decoration? outerDecoration;

  /// 外部padding
  final EdgeInsets? outerPadding;

  /// 自定义FocusNode
  final FocusNode? focusNode;

  /// 是否自动dispose focusNode，默认true
  final bool autoDisposeFocus;

  /// 内容padding
  final EdgeInsetsGeometry? contentPadding;

  /// 是否显示边框，获取焦点的时候显示主题色，否则显示灰色。默认false
  final bool showBorder;

  /// 新的值，每次build，如果[newValue]!=null,则更新这个值给[TextEditingController]
  final String? newValue;

  /// 新的光标位置，不传则在最后面
  final int? newOffset;

  const KqPadTextFiled(
      {Key? key,
      this.multiline = false,
      this.inputType,
      this.textInputAction,
      this.editable = true,
      this.autofocus = false,
      this.defOffset,
      this.useParentHeight = false,
      this.contentPadding,
      this.forceShowPlaceHolder = false,
      this.maxLines,
      this.fontSize,
      this.textColor,
      this.placeHolderTextColor,
      this.maxCharCount,
      this.placeHolder,
      this.password = false,
      this.textAlign,
      this.textAlignVertical,
      this.controller,
      this.onChanged,
      this.onChangedWithEditController,
      this.inputFormatters,
      this.cursorColor,
      this.selectionColor,
      this.defValue,
      this.newValue,
      this.newOffset,
      this.onCleared,
      this.onFocusChanged,
      this.onSubmitted,
      this.textStyle,
      this.hintStyle,
      this.cursorHeight,
      this.cursorRadius,
      this.counterStyle,
      this.counter,
      this.counterText = '',
      this.strutStyle,
      this.customLeftWidget,
      this.customRightWidget,
      this.fixedHeight,
      this.outerDecoration,
      this.outerPadding,
      this.isCollapsed = true,
      this.focusNode,
      this.autoDisposeFocus = true,
      this.unFocusWhenCleared = false,
      this.enableClearButton = false,
      this.showBorder = false,
      this.onMonitor})
      : super(key: key);

  @override
  _KqPadTextFiledState createState() => _KqPadTextFiledState();
}

class _KqPadTextFiledState extends State<KqPadTextFiled> {
  bool _hasValue = false;
  bool _hasFocus = false;

  /// TextEditingController
  TextEditingController? _controller;

  final KqPadClearButtonVisibleController _clearButtonVisibleController = KqPadClearButtonVisibleController();

  FocusNode? _focusNode;

  /// 等待时间500毫秒
  final int _waitTime = 500;

  /// 计时器
  Timer? timer;

  @override
  void initState() {
    initController();
    _focusNode ??= widget.focusNode;
    _focusNode ??= FocusNode();
    _focusNode?.addListener(() {
      if (widget.onFocusChanged != null) {
        widget.onFocusChanged!(_focusNode?.hasFocus ?? false);
      }
      _hasFocus = _focusNode?.hasFocus ?? false;
      if (widget.enableClearButton) {
        _clearButtonVisibleController.update();
      }
      if (widget.showBorder) {
        setState(() {});
      }
    });
    if (widget.autofocus) {
      _focusNode?.requestFocus();
    }

    if (_controller != null && widget.newValue != null) {
      TextFiledUtil.setValue(_controller!, widget.newValue ?? '',
          offset: widget.newOffset, keepOffset: true);
    }

    super.initState();
  }

  initController({bool initState = true}) {
    _controller = widget.controller ?? TextEditingController();
    if (initState) {
      if (widget.defValue != null) {
        TextFiledUtil.setValue(_controller!, widget.defValue!,
            offset: widget.defOffset, keepOffset: true);
      }
    }
    _hasValue = _controller != null && (_controller?.text.isNotEmpty ?? false);
  }

  @override
  void didUpdateWidget(covariant KqPadTextFiled oldWidget) {
    if (widget.controller != null && widget.controller != _controller) {
      if (_controller != null) {
        TextFiledUtil.setValue(widget.controller!, _controller!.text);
      }
      initController(initState: false);
    } else {
      if (_controller != null &&
          _controller!.text != widget.newValue &&
          (oldWidget.newValue != widget.newValue || widget.newValue != null)) {
        TextFiledUtil.setValue(_controller!, widget.newValue ?? '',
            offset: widget.newOffset, keepOffset: true);
      }
    }

    if (widget.focusNode != oldWidget.focusNode) {
      _focusNode = widget.focusNode;
      _focusNode ??= FocusNode();
      _focusNode?.addListener(() {
        if (widget.onFocusChanged != null) {
          widget.onFocusChanged!(_focusNode?.hasFocus ?? false);
        }
        _hasFocus = _focusNode?.hasFocus ?? false;
        if (widget.enableClearButton) {
          _clearButtonVisibleController.update();
        }
        if (widget.showBorder) {
          setState(() {});
        }
      });
      if (widget.autofocus) {
        _focusNode?.requestFocus();
      }
    }
    super.didUpdateWidget(oldWidget);
  }

  void _startTimer() {
    //计时器，每[_waitTime]毫秒执行一次
    var period = Duration(milliseconds: _waitTime);
    if (timer != null && timer!.isActive) {
      timer?.cancel();
    }
    timer = Timer(period, () {
      if (mounted) {
        widget.onMonitor?.call(_controller?.text ?? '');
      }
    });
  }

  /// 清空文字
  void _clearText() {
    _controller?.clear();
    _hasValue = false;
    if (widget.enableClearButton) {
      _clearButtonVisibleController.update();
    }
    if (widget.unFocusWhenCleared) {
      _focusNode?.unfocus();
    }
    if (widget.onChanged != null) {
      widget.onChanged!('');
    }
  }

  @override
  Widget build(BuildContext context) {
    Color cursorColor = widget.cursorColor ??
        KqPadThemeManager.instance.getConfig().commonConfig.mainColor ??
        KqPadThemeColors.bgBlue;
    List<Widget> children = [];
    //自定义左边
    if (widget.customLeftWidget != null) {
      children.add(widget.customLeftWidget!);
    }
    //输入框
    children.add(Expanded(
        child: Container(
      height: widget.useParentHeight ? context.height : null,
      decoration: widget.showBorder
          ? BoxDecoration(
              borderRadius: BorderRadius.circular(2.r),
              border: Border.all(
                  width: 1,
                  color: _hasFocus
                      ? KqPadThemeManager.getCommonConfig().mainColor!
                      : KqPadThemeColors.bgEB))
          : null,
      child: TextField(
        autofocus: widget.autofocus,
        focusNode: _focusNode,
        keyboardType: widget.inputType ??
            (widget.multiline ? TextInputType.multiline : TextInputType.text),
        textInputAction: widget.textInputAction ??
            (widget.multiline
                ? TextInputAction.newline
                : (Platform.isAndroid
                    ? TextInputAction.done
                    : TextInputAction.unspecified)),
        enabled: widget.editable,
        obscureText: widget.password,
        selectionControls: _getSelectionHandle(cursorColor),
        maxLines: widget.multiline ? widget.maxLines : 1,
        maxLength: widget.maxCharCount,
        textAlignVertical: widget.textAlignVertical ?? TextAlignVertical.center,
        style: widget.textStyle ??
            TextStyle(
              color: widget.textColor ??
                  KqPadThemeManager.instance
                      .getConfig()
                      .commonConfig
                      .inputColor ??
                  KqPadThemeColors.text59,
              fontSize: widget.fontSize ?? 14.sp,
            ),
        cursorHeight: widget.cursorHeight,
        cursorRadius: widget.cursorRadius,
        cursorColor: cursorColor,
        decoration: InputDecoration(
          border: InputBorder.none,
          hintStyle: widget.hintStyle ??
              TextStyle(
                color: (widget.editable || widget.forceShowPlaceHolder
                    ? (widget.placeHolderTextColor ??
                        KqPadThemeManager.instance
                            .getConfig()
                            .commonConfig
                            .placeHolderColor ??
                        KqPadThemeColors.textBF)
                    : KqPadThemeColors.bgTransparent),
                fontSize: widget.fontSize ?? 14.sp,
                overflow: TextOverflow.visible,
              ),
          hintText: widget.placeHolder ?? KqPadIntl.currentResource.pleaseEnter,
          counterText: widget.counterText,
          counter: widget.counter,
          counterStyle: widget.counterStyle,
          contentPadding: widget.contentPadding ??
              (widget.showBorder
                  ? EdgeInsets.symmetric(horizontal: 24.r, vertical: 15.r)
                  : EdgeInsets.zero),
          isCollapsed: widget.isCollapsed,
          isDense: true,
        ),
        textAlign: widget.textAlign ?? TextAlign.start,
        controller: _controller,
        strutStyle: widget.strutStyle,
        inputFormatters: widget.inputFormatters,
        onSubmitted: widget.onSubmitted,
        onChanged: (value) {
          if (Platform.isIOS) {
            Future.delayed(const Duration(milliseconds: 50), () {
              if (_controller?.value.isComposingRangeValid == true) {
                return;
              }
              _onChangedAction(value);
            });
          } else {
            _onChangedAction(value);
          }
        },
      ),
    )));

    //清空按钮
    children.add(GetBuilder<KqPadClearButtonVisibleController>(
        init: _clearButtonVisibleController,
        global: false,
        builder: (controller) {
          return Visibility(
            visible: _hasFocus && _hasValue && widget.enableClearButton,
            child: Row(
              children: [
                SizedBox(
                  width: 8.r,
                  height: 1,
                ),
                ExcludeFocus(
                  child: InkWell(
                    onTap: () {
                      _clearText();
                      if (widget.onCleared != null) {
                        widget.onCleared!();
                      }
                    },
                    child: Image.asset(Images.commonIcClose16,
                        width: 16.r,
                        height: 16.r,
                        fit: BoxFit.fill,
                        package: KqPadGlobal.packageName),
                  ),
                ),
                SizedBox(
                  width: 8.r,
                  height: 1,
                ),
              ],
            ),
          );
        }));
    //自定义右边
    if (widget.customRightWidget != null) {
      children.add(widget.customRightWidget!);
    }
    return DefaultSelectionStyle(
      cursorColor: cursorColor,
      selectionColor: widget.selectionColor ?? cursorColor.withOpacity(0.45),
      child: Container(
        decoration: widget.outerDecoration,
        padding: widget.outerPadding,
        height: widget.fixedHeight,
        child: Row(
          crossAxisAlignment: widget.useParentHeight
              ? CrossAxisAlignment.start
              : CrossAxisAlignment.center,
          children: children,
        ),
      ),
    );
  }

  /// 获取对应平台的SelectionHandle
  _getSelectionHandle(Color cursorColor) {
    final ThemeData theme = Theme.of(context);
    if (theme.platform == TargetPlatform.iOS) {
      return kqCupertinoTextSelectionControls..handleColor = cursorColor;
    } else if (theme.platform == TargetPlatform.android) {
      return kqMaterialTextSelectionControls..handleColor = cursorColor;
    }
  }

  _onChangedAction(String value) {
    _hasValue = value.isNotEmpty;
    if (widget.enableClearButton) {
      _clearButtonVisibleController.update();
    }
    if (widget.onChanged != null) {
      widget.onChanged!(value);
    }
    if (widget.onChangedWithEditController != null && _controller != null) {
      widget.onChangedWithEditController!(value, _controller!);
    }
    if (widget.onMonitor != null) {
      _startTimer();
    }
  }

  @override
  void dispose() {
    if (widget.autoDisposeFocus) {
      _focusNode?.dispose();
    }
    //退出时关闭计时器防止内存泄露
    timer?.cancel();
    super.dispose();
  }
}

class KqPadClearButtonVisibleController extends GetxController {}
